package com.android.dialer.extendboard;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.HashMap;

public class UsbHelper {
    private static final String TAG = "UsbHelper";
    private final String ACTION_USB_PERMISSION = "com.example.usb.USB_PERMISSION";
    private final int VENDOR_ID = 19530; // 替换为实际的 VendorID 4C4A
    private Context mContext;
    private Handler mHandler;
    private UsbManager usbManager;
    private UsbDevice currentDevice;
    private UsbDeviceConnection usbDeviceConnection;
    private UsbInterface usbInterface;
    private UsbEndpoint inEndpoint;
    private UsbEndpoint outEndpoint;
    private Thread usbReadThread;
    private volatile boolean isReading = false;
    private DataParseHelper dataParseHelper;

    private UsbBroadcastReceiver usbBroadcastReceiver;

    private class UsbBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true)) {
                        if (device != null) {
                            usbLog("USB permission granted for device: " + device.getDeviceName());
                        }

                        connectUsbDevice();
                    } else {
                        if (device != null) {
                            // permission denied
                            usbLog("USB permission denied for device: " + device.getDeviceName());
                        }

                        mHandler.sendEmptyMessage(ServiceConstant.MSG_TYPE_USB_PERMISSION_DENIED);
                    }
                }
            } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                usbLog("USB device attached");
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device != null) {
                    usbLog("USB device attached: " + device.getDeviceName());
                    if (device.getVendorId() == VENDOR_ID) {
                        // notify the handler to connect to the device
                        currentDevice = device;
                        if (checkUsbPermissionBeforeConnect()) {
                            connectUsbDevice();
                        }
                    } else {
                        usbLog("Not a target USB device: " + device.getDeviceName());
                    }
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                usbLog("USB device detached");
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device != null && device.equals(currentDevice)) {
                    usbLog("USB device disconnected");
                    disconnectUsbDevice();
                }
            }
        }
    }

    public void destroy() {
        if (usbDeviceConnection != null) {
            disconnectUsbDevice();
        }

        if (usbBroadcastReceiver != null) {
            mContext.unregisterReceiver(usbBroadcastReceiver);
        }
    }

    public UsbHelper(Context context, Handler handler) {
        super();
        mContext = context;
        mHandler = handler;
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        dataParseHelper = new DataParseHelper();
        dataParseHelper.setDataParseListener(new DataParseHelper.OnDataParsedListener() {
            @Override
            public void onMessageParsed(USBMessage message) {
                // Handle the parsed message
                if (mHandler != null) {
                    Message msg = mHandler.obtainMessage();
                    msg.what = ServiceConstant.MSG_TYPE_USB_GET_MESSAGE;
                    msg.obj = message;
                    mHandler.sendMessage(msg);
                }
            }
        });

        // register broadcast receiver for USB permission and device connection/disconnection
        usbBroadcastReceiver = new UsbBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // API 33+
            mContext.registerReceiver(usbBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
        } else { // API 32 and below
            mContext.registerReceiver(usbBroadcastReceiver, filter);
        }
    }

    protected void usbLog(String message) {
        Log.d(TAG, "usbLog: " + message);
        if (mHandler != null) {
            Message msg = mHandler.obtainMessage();
            msg.what = ServiceConstant.MSG_TYPE_USB_LOG_STRING;
            msg.obj = message;
            mHandler.sendMessage(msg);
        }
    }

    public boolean checkUsbPermissionBeforeConnect() {
        if (currentDevice == null) {
            usbLog("No USB device to check permission");
            return false;
        }

        if (usbManager.hasPermission(currentDevice)) {
            usbLog("Permission already granted for device: " + currentDevice.getDeviceName());
            return true;
        } else {
            int flags = PendingIntent.FLAG_UPDATE_CURRENT;
            flags |= PendingIntent.FLAG_IMMUTABLE;

            usbLog("Requesting permission for device: " + currentDevice.getDeviceName());

            PendingIntent permissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), flags);
            usbManager.requestPermission(currentDevice, permissionIntent);
        }

        return false;
    }

    public boolean checkUsbConnections() {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        if (deviceList.isEmpty()) {
            usbLog("No USB devices connected");
            return false;
        }

        for (UsbDevice device : deviceList.values()) {
            if (device.getVendorId() == VENDOR_ID) { // Replace with your device's VID and PID
                usbLog("Found target USB device: " + device.getDeviceName());
                currentDevice = device;
                return true;
            }
        }

        usbLog("No target USB device found");
        return false;
    }

    public boolean connectUsbDevice() {
        if (currentDevice != null) {
            usbLog("Connecting to USB device: " + currentDevice.getDeviceName());
            usbInterface = currentDevice.getInterface(0);

            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint endpoint = usbInterface.getEndpoint(i);
                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
                    if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                        inEndpoint = endpoint;
                    } else {
                        outEndpoint = endpoint;
                    }
                }
            }

            usbDeviceConnection = null;
            if (inEndpoint != null && outEndpoint != null) {
                usbDeviceConnection = usbManager.openDevice(currentDevice);
                if (usbDeviceConnection == null) {
                    usbLog("Failed to open USB device connection");
                    inEndpoint = null;
                    outEndpoint = null;
                    return false;
                }

                if (!usbDeviceConnection.claimInterface(usbInterface, true)) {
                    usbLog("Failed to claim USB interface");
                    usbDeviceConnection.close();
                    usbDeviceConnection = null;
                    inEndpoint = null;
                    outEndpoint = null;
                    return false;
                }

                // start a new thread to handle USB incoming data
                startUsbReadThread();

                if (mHandler != null) {
                    Message message = mHandler.obtainMessage();
                    message.what = ServiceConstant.MSG_TYPE_USB_CONNECT;
                    mHandler.sendMessage(message);
                }
                return true;
            } else {
                usbLog("No valid USB endpoints found");
                inEndpoint = null;
                outEndpoint = null;
            }
        } else {
            usbLog("No USB device to connect");
        }

        return false;
    }

    public void disconnectUsbDevice() {
        if (usbDeviceConnection != null) {
            isReading = false;
            if (usbReadThread != null) {
                try {
                    usbReadThread.join();
                } catch (InterruptedException e) {
                    usbLog("Error stopping USB read thread: " + e.getMessage());
                }
            }

            // stop the thread handling USB incoming data
            usbDeviceConnection.releaseInterface(usbInterface);
            usbDeviceConnection.close();
            usbDeviceConnection = null;
            inEndpoint = null;
            outEndpoint = null;
            usbLog("USB device disconnected");

            if (mHandler != null) {
                Message message = mHandler.obtainMessage();
                message.what = ServiceConstant.MSG_TYPE_USB_DISCONNECT;
                mHandler.sendMessage(message);
            }
        } else {
            usbLog("No USB device to disconnect");
        }
    }

    public boolean sendData(byte[] data) {
        if (usbDeviceConnection != null && outEndpoint != null) {
            int bytesSent = usbDeviceConnection.bulkTransfer(outEndpoint, data, data.length, 1000);
            if (bytesSent > 0) {
                usbLog("Sent " + bytesSent + " bytes to USB device");
                return true;
            } else {
                usbLog("Failed to send data to USB device");
            }
        } else {
            usbLog("No USB device connection or output endpoint");
        }
        return false;
    }

    protected void startUsbReadThread() {
        if (usbDeviceConnection == null || inEndpoint == null) {
            usbLog("Cannot start USB read thread: no connection or input endpoint");
            return;
        }

        isReading = true;
        usbReadThread = new Thread(() -> {
            byte[] buffer = new byte[inEndpoint.getMaxPacketSize()];
            while (isReading && !Thread.interrupted()) {
                int bytesRead = usbDeviceConnection.bulkTransfer(inEndpoint, buffer, buffer.length, 50);
                if (bytesRead > 0) {
                    usbLog("Received " + bytesRead + " bytes from USB device");
                    // 处理接收到的数据
                    dataParseHelper.parseStream(buffer, bytesRead);
                } else if (bytesRead < 0) {
//                    usbLog("Error reading data from USB device");
                }
            }
            usbLog("USB read thread stopped");
        });
        usbReadThread.start();
    }
}
